home *** CD-ROM | disk | FTP | other *** search
- /* National Institute of Standards and Technology (NIST)
- /* National Computer System Laboratory (NCSL)
- /* Office Systems Engineering (OSE) Group
- /* ********************************************************************
- /* D I S C L A I M E R
- /* (March 8, 1989)
- /*
- /* There is no warranty for the NIST NCSL OSE SGML parser and/or the NIST
- /* NCSL OSE SGML parser validation suite. If the SGML parser and/or
- /* validation suite is modified by someone else and passed on, NIST wants
- /* the parser's recipients to know that what they have is not what NIST
- /* distributed, so that any problems introduced by others will not
- /* reflect on our reputation.
- /*
- /* Policies
- /*
- /* 1. Anyone may copy and distribute verbatim copies of the SGML source
- /* code as received in any medium.
- /*
- /* 2. Anyone may modify your copy or copies of SGML parser source code or
- /* any portion of it, and copy and distribute such modifications provided
- /* that all modifications are clearly associated with the entity that
- /* performs the modifications.
- /*
- /* NO WARRANTY
- /* ===========
- /*
- /* NIST PROVIDES ABSOLUTELY NO WARRANTY. THE SGML PARSER AND VALIDATION
- /* SUITE ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
- /* EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- /* THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS
- /* WITH YOU. SHOULD THE SGML PARSER OR VALIDATION SUITE PROVE DEFECTIVE,
- /* YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
- /*
- /* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL NIST BE LIABLE FOR
- /* DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
- /* INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
- /* INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
- /* BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
- /* FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
- /* NIST) THE PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF
- /* SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
- */
-
- /************************************************************************/
- /* TITLE: SGML PARSER */
- /* SYSTEM: DOCUMENT PROCESSOR */
- /* SUBSYSTEM: */
- /* SOURCE FILE: DIINIT.C */
- /* AUTHOR: Steven Lindeman, Fred Maples */
- /* */
- /* DATE CREATED: */
- /* LAST MODIFIED: */
- /* */
- /* REVISIONS */
- /* WHEN WHO WHY */
- /************************************************************************/
- #include <stdio.h>
- #include <fcntl.h>
- #include "didefs.h"
- #include "diglobal.h"
-
- /*------------------------------------------------------*/
- /* C H E C K O P T */
- /* Reads the command line for document name to */
- /* be parsed and options to be applied. */
- /*------------------------------------------------------*/
- void checkopt(argc,argv,path,delete_temps,bld_ctr)
- int argc;
- char *argv[],path[];
- BOOLEAN *delete_temps,*bld_ctr;
- {
- FILE *fopen();
- int thisarg,fprintf(),fputc();
- long seekpos,atol();
- void semantic();
- char *cptr;
-
- if (argc < 3) {
- printf("INVALID COMMAND LINE PARAMETERS. Valid parameters are:\n");
- printf("PARSE3 <input-doc> -P<###> -T<path-name> -3<#> -N -F");
- exit(99);
- }
- if ((indoc=fopen(argv[1],"rb")) == NULL) { /* machine dependent */
- printf("Unknown source document file '%s'\n",argv[1]);
- exit(99);
- }
- #ifdef FRED
- ctrfile = get_char_mem(strlen(argv[1])+4);
- strcpy(ctrfile,argv[1]);
-
- for (cptr=ctrfile+strlen(ctrfile); *cptr!='.'&& *cptr!=DIR_SEPERATOR; cptr--);
- if (*cptr == '.')
- strcpy(cptr,".CTR");
- else
- strcat(ctrfile,".CTR");
- #else
- ctrfile = "CTRFILE.CTR";
- #endif
- fpstack[fpindx=0] = indoc;
- seekpos = atol(argv[2]+2);
- thisarg = 3;
- *bld_ctr = TRUE;
- applic = nullfnc;
- our_fprintf = print_ctr = fprintf;
- our_fputc = put_ctr = fputc;
- path[0] = '\0';
- *delete_temps = TRUE;
-
- while(argc > thisarg) {
- switch(*(argv[thisarg]+1)) {
- case 'T':
- strcpy(path,argv[thisarg]+2);
- break;
- case 'N':
- *bld_ctr = FALSE;
- print_ctr = put_ctr = nullfnc;
- break;
- case 'F':
- *delete_temps = FALSE;
- break;
- case 'S':
- applic = semantics;
- break;
- case 'H':
- printf("\n SGML Document Element Parser\n");
- printf(" Parses document elements in conformance with ISO 8879\n");
- printf("\n ------------ Version 0.16 08-Jul-87 -------------\n");
- printf(" Assuming Core Concrete Syntax\n");
- printf(" --------------------------------------------------\n\n");
- printf("Parsing document... %s\n",argv[1]);
- break;
- }
- thisarg++;
- }
- fseek(indoc,seekpos,0); /* seekpos is offset from file beginning */
-
- if (*bld_ctr && (ctrfp=fopen(ctrfile,"w")) == NULL) {
- printf("Unable to create CTR output file '%s'.\n",ctrfile);
- exit(99);
- }
- (*print_ctr)(ctrfp,"Canonical Test Result:");
- return;
- }
-
- /*------------------------------------------------------*/
- /* C H A N G E _ T R E E S */
- /* This routine is used to ensure that 'token' is */
- /* is a valid index into the symbol table array. */
- /* All of the trees and AND lists are traversed */
- /* and the 'nodeid's are replaced with the corr- */
- /* esponding new token indexes. */
- /*------------------------------------------------------*/
- void change_trees(ptr,numsym)
- TNODE *ptr;
- int numsym;
- {
- TNODE *currp;
- register short i;
-
- if (ptr != NULL)
- if (ptr->nodeid == AND) {
- currp = ptr->u.llptr;
- while(currp->next != ptr->u.llptr) {
- change_trees(currp,numsym);
- currp = currp->next;
- }
- change_trees(currp,numsym);
- }
- else {
- change_trees(ptr->left,numsym);
- change_trees(ptr->u.right,numsym);
- for (i=0; i<numsym && !ptr->changed; i++)
- if (ptr->nodeid == symtable[i].tokenid) {
- ptr->nodeid = i;
- ptr->changed = TRUE;
- }
- }
- return;
- }
-
- /*------------------------------------------------------*/
- /* C H A N G E _ E X C E P T S */
- /* This routine is used to ensure that 'token' is */
- /* is a valid index into the symbol table array. */
- /* All of the entries in the exception lists are */
- /* replaced with the corresponding new token */
- /* indexes. */
- /*------------------------------------------------------*/
- void change_excepts(headexcptr,numsym)
- EXCEPTDESC *headexcptr;
- int numsym;
- {
- register int i;
- EXCEPTDESC *excptr;
-
- /* This code assumes that an exception cannot include or exclude itself */
- for (i=0; i < numsym; i++) {
- for (excptr=headexcptr; excptr!=NULL; excptr=excptr->nextlocal)
- if (excptr->tokenid==symtable[i].tokenid && !excptr->changed) {
- excptr->changed = TRUE;
- excptr->tokenid = i;
- }
- }
- return;
- }
-
- /*------------------------------------------------------*/
- /* B U I L D A T T R */
- /* Builds a multi-linked list of attribute def- */
- /* initions from the input file 'attrfile.dat'. */
- /* A pointer to the newly built list is returned */
- /* or NULL if there were no attributes found in */
- /* the file. */
- /*------------------------------------------------------*/
- ATTRDESC *buildattr(attrfd)
- int attrfd;
- {
- ATTRDESC *retptr,*thisptr;
- unsigned numattr;
- register int i,j;
- char buffer[LITLEN];
-
- retptr = thisptr = adalloc(); /* first one */
- read(attrfd,&numattr,sizeof(int));
- for (i=1; i<=numattr; i++) {
- memset(thisptr->attrname,'\0',NAMELEN+1);
- read(attrfd,thisptr->attrname,NAMELEN);
- NULLTERM(thisptr->attrname);
- read(attrfd,&(thisptr->dvcode),sizeof(DECLVAL));
- read(attrfd,&(thisptr->defcode),sizeof(ADFLT));
- j = 0;
- read(attrfd,buffer,sizeof(char));
- while(buffer[j] != '\0')
- read(attrfd,&(buffer[++j]),sizeof(char));
- switch(thisptr->defcode) {
- case A_UNFIXED:
- case A_FIXED:
- thisptr->u2.currdef = get_char_mem(j+1);
- strncpy(thisptr->u2.currdef,buffer,j+1);
- break;
- default:
- thisptr->u2.currgrp = NULL; /* could set currgrp or currdef */
- break;
- }
- thisptr->groupp = buildgroup(attrfd);
- thisptr->next = (i == numattr) ? NULL : adalloc();
- thisptr = thisptr->next;
- }
- return(retptr);
- }
-
- /*------------------------------------------------------*/
- /* B U I L D E X C E P T */
- /* This routine builds a linked list containing */
- /* the inclusion or exclusion exceptions for a */
- /* token. A pointer to the newly built list is */
- /* returned or NULL is returned if there were no */
- /* exceptions found in the file. */
- /*------------------------------------------------------*/
- EXCEPTDESC *build_except(exceptfd)
- int exceptfd;
- {
- EXCEPTDESC *curr,*retptr;
- register int i;
- unsigned num_except;
-
- retptr = NULL;
- read(exceptfd,&num_except,sizeof(int));
- for (i=0; i<num_except; i++) {
- if (i == 0)
- curr = retptr = exalloc();
- else
- curr = curr->nextlocal = curr->nextglobal = exalloc();
- read(exceptfd,&(curr->tokenid),sizeof(int));
- curr->changed = FALSE; /* not been changed yet for new indexes */
- }
- if (retptr != NULL)
- curr->nextlocal = curr->nextglobal = NULL;
- return(retptr);
- }
-
- /*------------------------------------------------------*/
- /* B U I L D E N T I T Y */
- /* This routine builds a linked list containing */
- /* the general entity names and values. A ptr */
- /* to the newly built list is returned or NULL */
- /* if there were no entities found in the file. */
- /*------------------------------------------------------*/
- ENTITYDESC *build_entity(entityfd)
- int entityfd;
- {
- ENTITYDESC *thisptr,*retptr;
- int length;
-
- retptr = NULL; /* length of reference */
- while(read(entityfd,&length,sizeof(int)) > 0) { /* including ending null */
- if (retptr == NULL)
- thisptr = retptr = gealloc();
- else
- thisptr = thisptr->next = gealloc();
- memset(thisptr->entityname,'\0',NAMELEN+1);
- read(entityfd,thisptr->entityname,NAMELEN); /* name of entity */
- NULLTERM(thisptr->entityname);
- read(entityfd,&(thisptr->entitytype),sizeof(int));
- thisptr->entityvalue = get_char_mem(length);
- read(entityfd,thisptr->entityvalue,length); /* entity reference that */
- } /* null terminated */
- if (retptr != NULL)
- thisptr->next = NULL;
- return(retptr);
- }
-
- /*------------------------------------------------------*/
- /* B U I L D G R O U P */
- /* Builds a singly linked list, to be part of the */
- /* multi-linked list described in BUILDATTR, which */
- /* contains the members of the name token group. */
- /* If the number in the group equals zero, that is */
- /* there is no group, BUILDGROUP returns NULL */
- /* else a pointer to newly build list is returned. */
- /*------------------------------------------------------*/
- GROUPDESC *buildgroup(attrfd)
- int attrfd;
- {
- GROUPDESC *retptr,*thisptr;
- unsigned numgroup;
- register int i;
-
- read(attrfd,&numgroup,sizeof(int));
- if (numgroup == 0)
- retptr = NULL;
- else
- retptr = thisptr = gralloc(); /* get first one */
- for (i=1; i<=numgroup; i++) {
- memset(thisptr->groupname,'\0',NAMELEN+1);
- read(attrfd,thisptr->groupname,NAMELEN);
- NULLTERM(thisptr->groupname);
- thisptr->next = (i == numgroup) ? NULL : gralloc();
- thisptr = thisptr->next;
- }
- return(retptr);
- }
-
- /*--------------------------------------------------------------*/
- /* B U I L D _ T A B L E */
- /* This routine is done as part of the initialization */
- /* process. It sets up memory for the symbol table of */
- /* generic identifiers and goes off to build the content */
- /* model for each one. */
- /*--------------------------------------------------------------*/
- build_table(path)
- char path[];
- {
- char filename[PATHLEN];
- register int i;
- int tablefd,count;
- SYMBREC srec;
-
- sprintf(filename,"%s%s",path,"dtdfile.sgm");
- if ((tablefd=open(filename,O_RDONLY)) == -1) /* open file */
- ourexit(2,"Unknown document type definition file\n");
-
- read(tablefd,&count,sizeof(int)); /* read number of symbols in table */
- read(tablefd,&rootid,sizeof(int)); /* read the root symbol id */
-
- if ((symtable=(STPTR) malloc((count)*sizeof(STENTRY))) == NULL)
- ourexit(2,"\nInsufficient memory in parse3.\n");
-
- for (i=0; i < count; i++) { /* read each entry into symtable */
- read(tablefd,&srec,sizeof(SYMBREC));
- memset(symtable[i].nametoken,'\0',NAMELEN+1);
- strncpy(symtable[i].nametoken,srec.Sname,NAMELEN);
- NULLTERM(symtable[i].nametoken);
- symtable[i].tokenid = srec.Sid;
- /* minimization, NONE, START, END, BOTH */
- symtable[i].miniexcept = srec.Smin;
- symtable[i].adptr = NULL; /* assumes there are no attributes */
- symtable[i].inclusion = symtable[i].exclusion = NULL;
- symtable[i].content_type = ELEMENT_CONTENT; /* just an assumption */
- symtable[i].num_open = 0;
- }
-
- for (i=0; i < count; i++) /* build the content model for each element */
- symtable[i].cmptr = buildtree(tablefd,&dontcare,&(symtable[i].content_type));
- if (close(tablefd) != 0) {
- printf("Unable to close 'dtdfile.sgm'.\n");
- exit(99);
- }
- return(count);
- }
-
- /*------------------------------------------------------*/
- /* B U I L D T R E E */
- /* */
- /* Called by :INIT, BUILDTREE */
- /* */
- /* Returns :ptr to the root node in */
- /* the tree. */
- /* */
- /* Builds the content models as binary */
- /* trees for the given symbol table */
- /* entry. */
- /*------------------------------------------------------*/
- TNODE *buildtree(tablefd,oiopt,content_type)
- int tablefd;
- BOOLEAN *oiopt;
- int *content_type;
- {
- TNODE *ptr,*currp;
- DTDREC drec;
- unsigned numands;
- register int i;
- BOOLEAN leftoiopt,rightoiopt,listoiopt;
-
- /* If a given node has an optional occurrence indicator,
- then everything below is essentially optional. */
-
- read(tablefd,&drec,sizeof(DTDREC)); /* reads nodeid & occurind */
-
- ptr = talloc(); /* build a node */
- ptr->nodeid = drec.Dtoken;
- ptr->copyoi = ptr->occurind = drec.Doi;
- ptr->contreq = ptr->copycontreq = drec.Dcontreq;
- ptr->changed = ptr->contref_attr = FALSE;
- switch(ptr->nodeid) {
- case COMMA:
- ptr->left = buildtree(tablefd,&leftoiopt,content_type);
- ptr->u.right = buildtree(tablefd,&rightoiopt,content_type);
- if ((leftoiopt&&rightoiopt) && (testoi(ptr)==PLUS||testoi(ptr)==ONE)) {
- *oiopt = TRUE;
- reduceoi(ptr);
- }
- else
- *oiopt = FALSE;
- break;
- case OR:
- ptr->left = buildtree(tablefd,&leftoiopt,content_type);
- ptr->u.right = buildtree(tablefd,&rightoiopt,content_type);
- if ((leftoiopt||rightoiopt) && (testoi(ptr)==PLUS||testoi(ptr)==ONE)) {
- *oiopt = TRUE;
- reduceoi(ptr);
- }
- else
- *oiopt = FALSE;
- break;
- case AND:
- read(tablefd,&numands,sizeof(int)); /* number of elem in & group */
- currp = ptr->u.llptr = buildtree(tablefd,&listoiopt,content_type);
- *oiopt = listoiopt; /* first node in list */
- for (i=1; i<numands; i++) {
- currp->next = buildtree(tablefd,&listoiopt,content_type);
- if (listoiopt == FALSE) /* once false, can never change */
- *oiopt = FALSE;
- currp = currp->next;
- }
- currp->next = ptr->u.llptr; /* make it circular */
- if ((*oiopt==TRUE) && (testoi(ptr)==PLUS||testoi(ptr)==ONE))
- reduceoi(ptr);
- break;
- default:
- if (ptr->nodeid < 0) /* ANY, CDATA, RCDATA, PCDATA, or EMPTY */
- *content_type = OTHER_CONTENT;
- *oiopt = (testoi(ptr) == OPT) ? TRUE : FALSE;
- ptr->left = NULL; /* null left pointer */
- ptr->u.right = NULL; /* null right pointer */
- break;
- }
- return(ptr);
- }
-
- /*--------------------------------------------------------------*/
- /* E X P A N D _ A N Y */
- /* This routine expands the declaration for content of */
- /* ANY to mixed content in which parsed character data */
- /* and any elements defined in the same DTD are allowed. */
- /* A pointer to the newly built tree is returned. */
- /*--------------------------------------------------------------*/
- TNODE *expand_any(numsym)
- int numsym;
- {
- register TNODE *retptr;
- static int thissym = -1;
-
- retptr = talloc();
- retptr->nodeid = OR;
- retptr->contreq = retptr->copycontreq = C_NEVERO; /* not contextually required */
- retptr->changed = FALSE;
- retptr->contref_attr = FALSE;
-
- retptr->left = talloc();
- retptr->left->changed = retptr->left->contref_attr = FALSE;
- retptr->left->contreq = retptr->left->copycontreq = C_NEVERO;
-
- switch(thissym) {
- case -1:
- retptr->left->nodeid = PCDATA;
- retptr->occurind = retptr->copyoi = '*';
- retptr->left->occurind = '*';
- break;
- default:
- retptr->left->nodeid = symtable[thissym].tokenid;
- retptr->occurind = retptr->copyoi = '?';
- retptr->left->occurind = retptr->left->copyoi = '?';
- break;
- }
- retptr->left->left = retptr->left->u.right = NULL;
- if (++thissym < numsym-1)
- retptr->u.right = expand_any(numsym);
- else {
- retptr->u.right = talloc();
- retptr->u.right->nodeid = symtable[thissym].tokenid;
- retptr->u.right->left = retptr->u.right->u.right = NULL;
- retptr->u.right->changed = retptr->u.right->contref_attr = FALSE;
- retptr->u.right->contreq = retptr->u.right->copycontreq = C_NEVERO;
- retptr->u.right->occurind = retptr->u.right->occurind = '?';
- thissym = -1;
- }
- return(retptr);
- }
-
- /*-------------------------------------------------------------------*/
- /* I N I T */
- /* Called by :MAIN */
- /* Returns :VOID */
- /* */
- /* Initializes :symbol table, binary tree, number of symbols */
- /* rootid */
- /* */
- /* The symbol table is an array of structures. The structure */
- /* has three members; nametoken, tokenid, and cmptr. */
- /* The nametoken is a character array which contains the name */
- /* of a token. */
- /* The tokenid is an integer used to uniquely represent the */
- /* nametoken. */
- /* The cmptr (content model pointer) is an integer pointer that */
- /* points to the root node of a binary tree. The binary tree */
- /* is used the represent the content model associated with */
- /* each nametoken. */
- /*-------------------------------------------------------------------*/
- void init(numsym,genthead,penthead,path)
- int *numsym;
- ENTITYDESC **genthead,**penthead;
- char path[];
- {
- BOOLEAN root_changed=FALSE;
- int gentityfd,attrfd,tokenids[GRPCNT],exceptfd,except_elt,pentityfd;
- unsigned num_elem;
- register int i;
- char filename[PATHLEN];
-
- sprintf(filename,"%s%s",path,"attrfile.sgm");
- if ((attrfd=open(filename,O_RDONLY)) == -1)
- ourexit(2,"Unknown attribute file\n");
-
- sprintf(filename,"%s%s",path,"greffile.sgm");
- if ((gentityfd=open(filename,O_RDONLY)) == -1)
- ourexit(2,"Unknown general entity file\n");
-
- sprintf(filename,"%s%s",path,"preffile.sgm");
- if ((pentityfd=open(filename,O_RDONLY)) == -1)
- ourexit(2,"Unknown parameter entity file\n");
-
- sprintf(filename,"%s%s",path,"except.sgm");
- if ((exceptfd=open(filename,O_RDONLY)) == -1)
- ourexit(2,"Unknown exception file\n");
-
- idhead = idrefhead = NULL; /* linked list of ID and IDREF values */
- /* in all the attribute specifications */
- currexcl = currincl = NULL; /* linked list of current exclusion */
- /* and inclusion exceptions */
- stptr = NULL; /* head pointer of input stack */
-
- state = GETNEW;
- sp = entitylevel = num_open_ms = 0;
- open_cdata_ms = open_rcdata_ms = FALSE;
- head = NULL;
-
- /* creates lists of general and parameter entities */
- *genthead = build_entity(gentityfd);
- *penthead = build_entity(pentityfd);
-
- *numsym = build_table(path);
-
- read(exceptfd,&num_elem,sizeof(int));
- for (i=0; i<num_elem; i++) { /* build list of inclusion */
- read(exceptfd,&except_elt,sizeof(int)); /* exceptions for each element */
- symtable[except_elt].inclusion = build_except(exceptfd);
- }
- read(exceptfd,&num_elem,sizeof(int));
- for (i=0; i<num_elem; i++) { /* build list of exclusion */
- read(exceptfd,&except_elt,sizeof(int)); /* exceptions for each element */
- symtable[except_elt].exclusion = build_except(exceptfd);
- }
-
- read(attrfd,&num_elem,sizeof(int));
- while(num_elem != -1) {
- for (i=0; i < num_elem; i++)
- read(attrfd,tokenids+i,sizeof(int));
- symtable[tokenids[0]].adptr = buildattr(attrfd);
- for (i=1; i < num_elem; i++)
- symtable[tokenids[i]].adptr = symtable[tokenids[0]].adptr;
- read(attrfd,&num_elem,sizeof(int));
- }
- /* get rid of content model defined as ANY and */
- /* build a new model, expanded out with PCDATA */
- /* and every element in the symbol table */
- for (i=0; i < *numsym; i++)
- if (symtable[i].cmptr->nodeid == ANY) {
- free((char *)symtable[i].cmptr);
- symtable[i].cmptr = expand_any(*numsym);
- }
-
- qsort(symtable,*numsym,sizeof(STENTRY),compare); /* sort the table */
-
- for (i=0; i < *numsym; i++) {
- change_trees(symtable[i].cmptr,*numsym);
- change_excepts(symtable[i].inclusion,*numsym);
- change_excepts(symtable[i].exclusion,*numsym);
- if (rootid==symtable[i].tokenid && !root_changed) {
- root_changed = TRUE;
- rootid = i;
- }
- }
- for (i=0; i < *numsym; i++)
- symtable[i].tokenid = i;
-
- if (close(attrfd)!=0 || close(gentityfd)!=0 ||
- close(exceptfd)!=0 || close(pentityfd)!=0) {
- printf("Unable to close intermediate files.\n");
- exit(99);
- }
- return;
- }
-
- /*------------------------------------------------------*/
- /* C H A N G E _ R I G H T */
- /* This routine is used to keep up with the */
- /* flag called 'contreq' which is found on each */
- /* node of the content model tree. If you are */
- /* in a sequence group, and the left side wasn't */
- /* found, the tag for the token found on the right */
- /* side should become never omissable. If it */
- /* was found on the left, the right side then */
- /* becomes omissable. */
- /*------------------------------------------------------*/
- void change_right(ptr,leftretval)
- TNODE *ptr;
- int leftretval;
- {
- if (ptr != NULL)
- if (leftretval==FOUND && ptr->contreq==C_SOMETIMESO)
- if (testoi(ptr) == PLUS)
- ptr->contreq = C_FTO;
- else
- ptr->contreq = C_ALWAYSO;
- else
- if (leftretval==NFDHT && ptr->contreq==C_SOMETIMESO)
- ptr->contreq = C_NEVERO;
- return;
- }
-